package com.ruoyi.exam.http;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.system.domain.ExamPaper;
import com.ruoyi.system.domain.ExamQuestion;
import com.ruoyi.system.domain.ExamAnswer;
import com.ruoyi.system.domain.ExamStudentRecord;
import com.ruoyi.system.service.IExamPaperService;
import com.ruoyi.system.service.IExamQuestionService;
import com.ruoyi.system.service.IExamAnswerService;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;

@Service
public class ExamHttpClient {

    @Autowired
    private IExamPaperService examPaperService;
    @Autowired
    private IExamQuestionService examQuestionService;
    @Autowired
    private IExamAnswerService examAnswerService;

    // AI出题API URL
    private static final String API_URL = "http://127.0.0.1:88/v1"; // 基础 URL
    private static final String API_KEY = "app-80bv79ehZrlDYGwJuewgzVKL"; // 替换为实际 API Key
    private static final OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(100, TimeUnit.SECONDS)
        .readTimeout(100, TimeUnit.SECONDS)
        .writeTimeout(100, TimeUnit.SECONDS)
        .build();

    /**
     * 请求AI生成试卷（实例方法，不再是static）
     */
    public SseEmitter generateExamPaper(String subject, Long teacherId, Long classId,
                                        Date startTime, Date endTime) {
        // 构建请求体
        StringBuilder jsonBodyBuilder = new StringBuilder();
        jsonBodyBuilder.append("{");
        jsonBodyBuilder.append("\"query\": \"").append(subject).append("\",");
        jsonBodyBuilder.append("\"user\": \"teacher_").append(teacherId).append("\",");
        jsonBodyBuilder.append("\"response_mode\": \"streaming\",");
        jsonBodyBuilder.append("\"inputs\": {}");
        jsonBodyBuilder.append("}");

        String jsonData = jsonBodyBuilder.toString();
        System.out.println("发送试卷生成请求: " + jsonData);

        // 创建试卷记录，等待填充内容
        ExamPaper examPaper = new ExamPaper();
        examPaper.setTitle(subject + "考试");
        examPaper.setTeacherId(teacherId);
        examPaper.setClassId(classId);
        examPaper.setStartTime(startTime);
        examPaper.setEndTime(endTime);
        examPaper.setAiPrompt(subject);
        examPaper.setCreateTime(new Date());
        examPaper.setStatus(0L); // 未开始

        // 构建请求
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, jsonData);

        Request request = new Request.Builder()
            .url(API_URL + "/chat-messages")
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .header("Accept", "text/event-stream")
            .post(body)
            .build();

        // 创建SseEmitter实例，0L表示不超时
        SseEmitter emitter = new SseEmitter(0L);
        System.out.println("创建SseEmitter实例");

        // 定义一个StringBuilder来累积AI回复内容
        StringBuilder aiResponseBuilder = new StringBuilder();

        // 在新线程中执行请求，避免阻塞
        new Thread(() -> {
            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    System.out.println("请求失败: " + response.code());
                    emitter.completeWithError(new Exception("API请求失败: " + response.code()));
                    return;
                }
                System.out.println("请求成功");

                if (response.body() != null) {
                    try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(response.body().byteStream()))) {
                        String line;
                        StringBuilder eventBuilder = new StringBuilder();
                        String eventName = null;

                        while ((line = reader.readLine()) != null) {
                            System.out.println("接收到行: " + line);

                            if (line.isEmpty()) {
                                // 省略
                            } else if (line.startsWith("event:")) {
                                eventName = line.substring(6).trim();
                            } else if (line.startsWith("data:")) {
                                String data = line.substring(5).trim();
                                eventBuilder.append(data);

                                try {
                                    JSONObject jsonObject = JSONObject.parseObject(data);

                                    // 处理逐块answer（如要前端实时展示，累加到builder即可，不用作入库）
                                    if (jsonObject.containsKey("event") && "message".equals(jsonObject.getString("event"))) {
                                        String answer = jsonObject.getString("answer");
                                        if (answer != null) {
                                            aiResponseBuilder.append(answer); // 可选
                                        }
                                    }

                                    // 这里新增：处理workflow_finished，提取outputs.answer作为最终内容
                                    if (jsonObject.containsKey("event") && "workflow_finished".equals(jsonObject.getString("event"))) {
                                        System.out.println("【调试】收到workflow_finished事件");

                                        JSONObject dataObj = jsonObject.getJSONObject("data");
                                        if (dataObj != null && dataObj.containsKey("outputs")) {
                                            JSONObject outputs = dataObj.getJSONObject("outputs");
                                            String finalPaperContent = outputs.getString("answer");
                                            System.out.println("【调试】最终AI生成试卷内容如下：\n" + finalPaperContent);

                                            // 保存AI原始回复
                                            examPaper.setAiRawResponse(finalPaperContent);

                                            // 解析试卷内容并保存
                                            parseAndSaveExamPaper(finalPaperContent, examPaper);

                                            // 通知前端试卷已保存
                                            JSONObject resultJson = new JSONObject();
                                            resultJson.put("status", "success");
                                            resultJson.put("message", "试卷已生成并保存");
                                            resultJson.put("paperId", examPaper.getId());
                                            emitter.send(SseEmitter.event().name("exam_saved").data(resultJson.toJSONString()));
                                        }
                                    }
                                } catch (Exception e) {
                                    // JSON解析失败，不处理
                                    System.err.println("【调试】解析AI返回JSON异常: " + e.getMessage() + "；内容=" + data);
                                }
                            }
                        }
                    }
                }

                // 完成发射器
                emitter.complete();

            } catch (IOException e) {
                System.err.println("流式传输错误: " + e.getMessage());
                e.printStackTrace();
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }

    /**
     * 解析AI生成的试卷内容并保存到数据库
     */
    private void parseAndSaveExamPaper(String paperContent, ExamPaper examPaper) {
        try {
            System.out.println("【调试】收到待解析AI试卷原文：\n" + paperContent);

            // 解析试卷元数据
            Pattern titlePattern = Pattern.compile("\\[试卷:([^\\]]+)\\]");
            Matcher titleMatcher = titlePattern.matcher(paperContent);
            if (titleMatcher.find()) {
                System.out.println("【调试】解析到试卷标题: " + titleMatcher.group(1));
                examPaper.setTitle(titleMatcher.group(1));
            } else {
                System.out.println("【调试】未匹配到试卷标题！");
            }

            // 解析总分和时长
            Pattern scorePattern = Pattern.compile("\\[总分:(\\d+)分\\|时长:(\\d+)分钟\\]");
            Matcher scoreMatcher = scorePattern.matcher(paperContent);
            if (scoreMatcher.find()) {
                System.out.println("【调试】解析到总分: " + scoreMatcher.group(1) + "，时长: " + scoreMatcher.group(2));
                examPaper.setTotalScore(Long.valueOf(scoreMatcher.group(1)));
                examPaper.setDuration(Long.valueOf(scoreMatcher.group(2)));
            } else {
                System.out.println("【调试】未匹配到总分和时长！");
            }

            System.out.println("【调试】保存试卷基本信息到数据库: " + examPaper);
            examPaperService.insertExamPaper(examPaper);

            // 解析题目
            Pattern questionPattern = Pattern.compile("<题目>([\\s\\S]*?)</题目>");
            Matcher questionMatcher = questionPattern.matcher(paperContent);
            int questionIndex = 0;
            while (questionMatcher.find()) {
                questionIndex++;
                String questionBlock = questionMatcher.group(1);
                System.out.println("【调试】解析到第" + questionIndex + "题块：\n" + questionBlock);

                // 创建题目对象
                ExamQuestion question = new ExamQuestion();
                question.setPaperId(examPaper.getId());

                // 解析题目类型
                Pattern typePattern = Pattern.compile("<类型>(.*?)</类型>");
                Matcher typeMatcher = typePattern.matcher(questionBlock);
                if (typeMatcher.find()) {
                    String type = typeMatcher.group(1);
                    question.setQuestionType(convertQuestionType(type));
                    System.out.println("【调试】第" + questionIndex + "题-类型: " + type);
                } else {
                    System.out.println("【调试】第" + questionIndex + "题未匹配到类型！");
                }

                // 解析题号
                Pattern numPattern = Pattern.compile("<编号>(\\d+)</编号>");
                Matcher numMatcher = numPattern.matcher(questionBlock);
                if (numMatcher.find()) {
                    question.setQuestionNumber(Long.valueOf(numMatcher.group(1)));
                    System.out.println("【调试】第" + questionIndex + "题-编号: " + numMatcher.group(1));
                } else {
                    System.out.println("【调试】第" + questionIndex + "题未匹配到编号！");
                }

                // 解析题干
                Pattern contentPattern = Pattern.compile("<题干>(.*?)</题干>", Pattern.DOTALL);
                Matcher contentMatcher = contentPattern.matcher(questionBlock);
                if (contentMatcher.find()) {
                    question.setQuestionContent(contentMatcher.group(1).trim());
                    System.out.println("【调试】第" + questionIndex + "题-题干: " + contentMatcher.group(1).trim());
                } else {
                    System.out.println("【调试】第" + questionIndex + "题未匹配到题干！");
                }

                // 解析选项（如有）
                Pattern optionsPattern = Pattern.compile("<选项>([\\s\\S]*?)</选项>");
                Matcher optionsMatcher = optionsPattern.matcher(questionBlock);
                if (optionsMatcher.find()) {
                    String optionsText = optionsMatcher.group(1);
                    JSONObject optionsJson = parseOptions(optionsText);
                    question.setOptions(optionsJson.toJSONString());
                    System.out.println("【调试】第" + questionIndex + "题-选项: " + optionsJson.toJSONString());
                } else {
                    System.out.println("【调试】第" + questionIndex + "题无选项或未匹配到选项");
                }

                // 解析分值 - 修改为默认值处理
                Pattern scorePattern2 = Pattern.compile("<分数>(.*?)</分数>");
                Matcher scoreMatcher2 = scorePattern2.matcher(questionBlock);
                if (scoreMatcher2.find()) {
                    String scoreStr = scoreMatcher2.group(1).trim();
                    // 处理可能有多个分数的情况
                    if (scoreStr.contains(",")) {
                        // 填空题多个空的情况，取总和
                        float totalScore = 0;
                        String[] scores = scoreStr.split(",");
                        for (String s : scores) {
                            totalScore += Float.parseFloat(s.trim());
                        }
                        question.setScore(totalScore);
                    } else {
                        question.setScore(Float.valueOf(scoreStr));
                    }
                    System.out.println("【调试】第" + questionIndex + "题-分数: " + scoreStr);
                } else {
                    // 未匹配到分数时，根据题型设置默认分数
                    String questionType = question.getQuestionType();
                    if ("essay".equals(questionType) || "coding".equals(questionType) || "other".equals(questionType)) {
                        question.setScore(10.0f); // 简答题、编程题默认10分
                        System.out.println("【调试】第" + questionIndex + "题未匹配到分数，设置默认分数10分");
                    } else {
                        question.setScore(5.0f); // 其他题型默认5分
                        System.out.println("【调试】第" + questionIndex + "题未匹配到分数，设置默认分数5分");
                    }
                }

                // 解析知识点
                Pattern kpPattern = Pattern.compile("<知识点>(.*?)</知识点>");
                Matcher kpMatcher = kpPattern.matcher(questionBlock);
                if (kpMatcher.find()) {
                    question.setKnowledgePoint(kpMatcher.group(1));
                    System.out.println("【调试】第" + questionIndex + "题-知识点: " + kpMatcher.group(1));
                } else {
                    System.out.println("【调试】第" + questionIndex + "题无知识点或未匹配到知识点");
                }

                // 解析评分标准（如有）
                Pattern criteriaPattern = Pattern.compile("<评分标准>(.*?)</评分标准>");
                Matcher criteriaMatcher = criteriaPattern.matcher(questionBlock);
                if (criteriaMatcher.find()) {
                    question.setScoringCriteria(criteriaMatcher.group(1));
                    System.out.println("【调试】第" + questionIndex + "题-评分标准: " + criteriaMatcher.group(1));
                } else {
                    System.out.println("【调试】第" + questionIndex + "题无评分标准或未匹配到评分标准");
                }

                // 保存题目
                System.out.println("【调试】第" + questionIndex + "题保存题目到数据库: " + question);
                examQuestionService.insertExamQuestion(question);

                // 解析答案 - 修改为处理嵌套代码块
                if ("coding".equals(question.getQuestionType()) || "other".equals(question.getQuestionType())) {
                    // 编程题和综合题的答案可能包含代码块，使用不同的解析方式
                    Pattern codeAnswerPattern = Pattern.compile("<答案>[\\s\\S]*?```[\\w]*\\s*([\\s\\S]*?)```[\\s\\S]*?</答案>");
                    Matcher codeAnswerMatcher = codeAnswerPattern.matcher(questionBlock);
                    if (codeAnswerMatcher.find()) {
                        String answerText = codeAnswerMatcher.group(1).trim();
                        System.out.println("【调试】第" + questionIndex + "题-编程题标准答案: " + answerText);

                        ExamAnswer answer = new ExamAnswer();
                        answer.setQuestionId(question.getId());
                        answer.setAnswerContent(answerText);
                        System.out.println("【调试】第" + questionIndex + "题-保存编程题标准答案到数据库: " + answer);
                        examAnswerService.insertExamAnswer(answer);
                    } else {
                        // 尝试使用常规答案解析
                        parseRegularAnswer(questionBlock, questionIndex, question);
                    }
                } else {
                    // 常规答案解析
                    parseRegularAnswer(questionBlock, questionIndex, question);
                }
            }

            System.out.println("【调试】全部题目和答案解析与保存流程完成。");

        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("解析试卷失败: " + e.getMessage());
        }
    }

    // 新增方法：解析常规答案
    private void parseRegularAnswer(String questionBlock, int questionIndex, ExamQuestion question) {
        Pattern answerPattern = Pattern.compile("<答案>(.*?)</答案>", Pattern.DOTALL);
        Matcher answerMatcher = answerPattern.matcher(questionBlock);
        if (answerMatcher.find()) {
            String answerText = answerMatcher.group(1).trim();
            System.out.println("【调试】第" + questionIndex + "题-标准答案: " + answerText);

            // 处理不同类型题目的答案
            if ("fill".equals(question.getQuestionType()) && answerText.contains(",")) {
                // 填空题，可能有多个空
                String[] blankAnswers = answerText.split(",");
                // 解析每空分值
                String[] blankScores = null;
                Pattern blankScorePattern = Pattern.compile("<分数>(.*?)</分数>");
                Matcher blankScoreMatcher = blankScorePattern.matcher(questionBlock);
                if (blankScoreMatcher.find() && blankScoreMatcher.group(1).contains(",")) {
                    blankScores = blankScoreMatcher.group(1).split(",");
                }
                for (int i = 0; i < blankAnswers.length; i++) {
                    ExamAnswer answer = new ExamAnswer();
                    answer.setQuestionId(question.getId());
                    answer.setAnswerContent(blankAnswers[i].trim());
                    answer.setBlankNumber((long) (i + 1));
                    if (blankScores != null && i < blankScores.length) {
                        answer.setBlankScore(BigDecimal.valueOf(Float.parseFloat(blankScores[i].trim())));
                    }
                    System.out.println("【调试】第" + questionIndex + "题-填空" + (i + 1) + "保存标准答案到数据库: " + answer);
                    examAnswerService.insertExamAnswer(answer);
                }
            } else {
                // 其他类型题目
                ExamAnswer answer = new ExamAnswer();
                answer.setQuestionId(question.getId());
                answer.setAnswerContent(answerText);
                System.out.println("【调试】第" + questionIndex + "题-保存标准答案到数据库: " + answer);
                examAnswerService.insertExamAnswer(answer);
            }
        } else {
            System.out.println("【调试】第" + questionIndex + "题未匹配到标准答案！");
        }
    }

    /**
     * 将中文题型转换为代码中的题型标识
     */
    private String convertQuestionType(String chineseType) {
        switch (chineseType) {
            case "单选题": return "single";
            case "多选题": return "multiple";
            case "填空题": return "fill";
            case "简答题": return "essay";
            case "编程题": return "coding";
            default: return "other";
        }
    }

    /**
     * 解析选项文本为JSON对象
     */
    private JSONObject parseOptions(String optionsText) {
        JSONObject optionsJson = new JSONObject();
        String[] lines = optionsText.split("\n");

        for (String line : lines) {
            line = line.trim();
            if (line.length() > 0 && line.charAt(0) >= 'A' && line.charAt(0) <= 'Z' && line.length() > 2) {
                String key = line.substring(0, 1);
                String value = line.substring(2).trim();
                optionsJson.put(key, value);
            }
        }
        return optionsJson;
    }

    /**
     * 提交学生答案
     */
    public String submitStudentAnswer(Long paperId, Long studentId,
                                      Long questionId, String answer) throws IOException {
        try {
            ExamStudentRecord record = new ExamStudentRecord();
            record.setPaperId(paperId);
            record.setStudentId(studentId);
            record.setQuestionId(questionId);
            record.setStudentAnswer(answer);
            record.setSubmitTime(new Date());

            // TODO: 这里你应该调用 IExamStudentRecordService 保存答案

            JSONObject result = new JSONObject();
            result.put("code", 200);
            result.put("msg", "答案提交成功");
            return result.toJSONString();
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("code", 500);
            error.put("msg", "答案提交失败：" + e.getMessage());
            return error.toJSONString();
        }
    }
}
